home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 2
/
Atari Mega Archive CD - Volume 2.iso
/
minix
/
up1510b.tgz
/
up1510b
/
src
/
commands
/
diskcheck.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-07-23
|
4KB
|
204 lines
/* diskcheck - test a disk for bad blocks Author: Andy Tanenbaum */
#include <sys/types.h>
#include <signal.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <minix/config.h>
#include <minix/const.h>
#undef printf
#define OK 0
#define PRINTFREQ 10
#define N 30
char purgebuf[BLOCK_SIZE * N];
char buf[BLOCK_SIZE], zero[BLOCK_SIZE];
int pat1[BLOCK_SIZE / 2], pat2[BLOCK_SIZE / 2];
int blk = -1; /* number of the block in buf, or -1 */
int pfd; /* file descriptor for purging */
int fd; /* file descriptor for data I/O */
unsigned initblock; /* first block to test */
unsigned curblock; /* current block */
unsigned limit; /* first block beyond test zone */
unsigned errors; /* # errors so far */
unsigned ct; /* # blocks read so far */
int intflag; /* set when signal seen */
extern errno;
long pos;
char *purgefile = "/dev/ram";
main(argc, argv)
int argc;
char *argv[];
{
unsigned b;
int i;
void catch();
signal(SIGINT, catch);
signal(SIGQUIT, catch);
if (argc != 4) usage();
if ((fd = open(argv[1], O_RDWR)) < 0) {
printf("Cannot open %s\n", argv[1]);
exit(1);
}
if ((pfd = open(purgefile, O_RDWR)) < 0) {
printf("Cannot open %s\n", purgefile);
exit(1);
}
initblock = atoi(argv[2]);
limit = initblock + atoi(argv[3]);
if (limit <= initblock) usage();
for (i = 0; i < BLOCK_SIZE / 2; i++) {
pat1[i] = i;
pat2[i] = 1000 - i;
}
for (b = initblock; b < limit; b++) {
if (intflag) break;
if (testblock(b) == ERROR) {
errors++;
if (blk == b) {
/* Read ok, write failed; try to restore block. */
lseek(fd, pos, SEEK_SET);
write(fd, buf, BLOCK_SIZE);
}
}
curblock = b;
ct++;
if (ct % PRINTFREQ == 0) status();
}
status();
exit(0);
}
int testblock(b)
unsigned b;
{
/* Read block b in, save it in buf. Then overwrite that block with a
* known test pattern and read it back. Finally, replace the block.
* Return OK or ERROR.
*/
int s;
blk = -1;
pos = (long) BLOCK_SIZE *(long) b;
purge_cache();
if (lseek(fd, pos, SEEK_SET) != pos) fatal("Cannot seek to block ", b);
/* Read block b into 'buf'. */
s = read(fd, buf, BLOCK_SIZE);
/* Test for various outcomes of the read. */
if (s == BLOCK_SIZE) {
blk = b;
if (wtest(pos, pat1) == ERROR) return(ERROR);
if (wtest(pos, pat2) == ERROR) return (ERROR);
lseek(fd, pos, SEEK_SET);
if (write(fd, buf, BLOCK_SIZE) != BLOCK_SIZE) {
nonfatal("Cannot rewrite block ", b);
return(ERROR);
} else {
return(OK);
}
}
if (s < 0) {
if (errno == EIO)
nonfatal("Read error on block ", b);
else {
printf("\nError. Read returned %d. errno=%d. ", s, errno);
fatal("Block ", b);
}
return(ERROR);
}
if (s == 0) fatal("End of file reached trying to read block ", b);
nonfatal("Read size error on block ", b);
}
status()
{
printf("%8u blocks tested, %u errors detected (last block tested = %5u)\r",
ct, errors, curblock);
}
nonfatal(s, b)
char *s;
unsigned b;
{
printf("\n%s%u\n", s, b);
}
fatal(s, b)
char *s;
unsigned b;
{
printf("\n%s%u\n", s, b);
status();
exit(1);
}
void catch(sig)
int sig; /* prototype says there has to be 1 arg */
{
signal(SIGINT, catch);
signal(SIGQUIT, catch);
intflag = 1;
}
usage()
{
printf("Usage: diskcheck device start-block block-count\n");
exit(1);
}
wtest(pos, pat)
long pos;
int pat[];
{
int testb[BLOCK_SIZE / 2];
int i;
lseek(fd, pos, SEEK_SET);
if (write(fd, (char *) pat, BLOCK_SIZE) != BLOCK_SIZE) return(ERROR);
sync(); /* force the write to the disk */
purge_cache();
lseek(fd, pos, SEEK_SET);
if (read(fd, (char *) testb, BLOCK_SIZE) != BLOCK_SIZE) return(ERROR);
for (i = 0; i < BLOCK_SIZE / 2; i++)
if (testb[i] != pat[i]) {
printf("%d %d\n", testb[i], pat[i]);
return(ERROR);
}
return(OK);
}
purge_cache()
{
/* Do enough reads that the cache is purged. */
int left, count, r;
pfd = open(purgefile, O_RDONLY);
left = NR_BUFS;
while (left > 0) {
count = (left < N ? left : N);
if ((r = read(pfd, purgebuf, count * BLOCK_SIZE)) != count * BLOCK_SIZE) {
printf("ERROR: count=%d left=%d r=%d. ", count, left, r);
fatal("Cannot purge cache. errno= ", errno);
}
left -= count;
}
close(pfd);
}